<?php
/**
 * Wrapper for persistent data (which exists between page loads) - Session vars or Cookie vars
 * Provides support for getting, setting or unsetting variables
 * (Note that for Cookies to work, no output must be sent to the browser while the object is still in use !)
 *
 * @todo Support Memcached for the future if necessary, or a Nosql mechanism based on SQLite3 or Files
 *
 * @author Highstrike (highstrike@gmail.com)
 * @package CargoClaims
 * @version 1.0.dev
 */
class MVC_Persist
{
	// Legacy compatibility, set this to PHPSESSID once "Hesk" is gone (or remove the session_name() thing completely)
	const SESSION_NAME = 'HESK';

	/**
	 * What type of vars to use ( session or cookie )
	 * @var string
	 */
	private $mode = null;

	private static $session_started = false;

	/**
	 * Initializes with one of the supported modes
	 * @param string $mode
	 * @throws MVC_Exception
	 */
	public function __construct($mode)
	{
		$this-> mode = strtolower($mode);
		if(!in_array($this-> mode, array('session','cookie')))
			throw new MVC_Exception("Unsupported Data Persistence mode: ". $mode);

		if($this-> mode == 'session' && self::$session_started == false) {
			session_name(self::SESSION_NAME);
			session_start();
			self::$session_started = true;
		}
	}

	/**
	 * Value set overloader
	 * @param string $var
	 * @param mixed $val
	 * @throws MVC_Exception
	 */
	public function __set($var, $val)
	{
		switch($this-> mode) {
			case 'session':
				$_SESSION[$var] = $val;
				break;
			case 'cookie':
				$_COOKIE[$var] = $val;
				$json_cookie = str_replace(
					array(",",";"," ","\t","\r","\n","\013","\014"),
					array("%2C","%3B","%20","%09","%0D","%0A","%0B","%0C"),
					json_encode($val)
				);
				setrawcookie($var, $json_cookie, time()+2592000, '/'); // TODO: Configurable Maxlife ( instead of 2592000 )
				break;
			default:
				throw new MVC_Exception("Unsupported Data Persistence mode: ");
		}
	}

	/**
	 * Value get overloader
	 * @param string $var
	 */
	public function &__get($var)
	{
		$null = null;
		switch($this-> mode) {
			case 'session':
				if(isset($_SESSION[$var]))
					return $_SESSION[$var];
				else
					return $null;
			case 'cookie':
				// TODO: direct access to the cookies not working like this, must have different implementation
				return isset($_COOKIE[$var])?json_decode($_COOKIE[$var], true):null;
		}
	}

	/**
	 * Value check overloader
	 * @param string $var
	 */
	public function __isset($var)
	{
		switch($this-> mode) {
			case 'session':
				return isset($_SESSION[$var]);
			case 'cookie':
				return isset($_COOKIE[$var]);
		}
	}

	/**
	 * Value remove overloader
	 * @param string $var
	 */
	public function __unset($var)
	{
		switch($this-> mode) {
			case 'session':
				unset($_SESSION[$var]);
				break;
			case 'cookie':
				unset($_COOKIE[$var]);
				setrawcookie($var, null, time()-31536000, '/');
				break;
		}
	}
}